# import tkinter as tk
# win=tk.Tk()
# win.title("yolo")
# win.geometry('400x350+200+200')
# win.iconbitmap('')
# frame1=tk.Frame(win)
# frame1.pack()
# frame_left=tk.Frame(frame1)
# tk.Label(frame_left,text='左侧标签1',bg='green',width=10,height=5).grid(row=0,column=0)
# tk.Label(frame_left,text='左侧标签2',bg='blue',width=10,height=5).grid(row=1,column=0)
# frame_left.pack(side=tk.LEFT)
# frame_right=tk.Frame(frame1)
# tk.Label(frame_right,text='右侧标签1',bg='gray',width=10,height=5).grid(row=0,column=1)
# tk.Label(frame_right,text='右侧标签2',bg='pink',width=10,height=5).grid(row=1,column=0)
# tk.Label(frame_right,text='右侧标签3',bg='purple',width=10,height=5).grid(row=1,column=1)
# frame_right.pack(side=tk.RIGHT)
# win.mainloop()
# from tkinter import *
# win=Tk()
# win.config(bg='#87CEEB')
# win.title("yolo")
# win.geometry('500x350+300+300')
# win.iconbitmap('')
# for i in range(36):
#     for j in range(36):
#         Button(win,text="("+str(i)+","+str(j)+")",bg='#D1EEEE').grid(row=i,column=j)
# Label(win,text="yolo",fg='blue',font=('楷体',12,'bold')).grid(row=4,column=11)
# win.mainloop()
import tkinter as tk
from tkinter import scrolledtext, filedialog, messagebox, colorchooser, simpledialog, ttk
from pathlib import Path
import json
import os
import shutil
from datetime import datetime, timedelta
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64

class SimpleNotepad:
    def __init__(self, root):
        self.root = root
        self.root.title("高级记事本")
        self.current_file = None
        self.dirty = False
        self.clipboard_history = []  # 剪贴板历史
        self.max_clipboard_history = 10  # 最大剪贴板历史记录数
        self.find_data = {"last_search": "", "case_sensitive": False}  # 查找相关数据
        
        # 笔记管理相关属性
        self.notes_tree = None
        self.folder_structure = {}
        self.current_folder_path = ""  # 当前选中的文件夹路径
        self.backup_dir = os.path.join(os.path.expanduser("~"), "NotepadBackups")
        self.encryption_key = None  # 加密密钥
        
        # 创建界面
        self.create_widgets()
        # 绑定事件处理
        self.bind_events()
        
        # 初始化文件夹结构
        self.init_folder_structure()
        # 加载笔记树
        self.load_notes_tree()

    def create_widgets(self):
        """创建程序界面组件"""
        # 创建主分割窗口
        self.paned_window = tk.PanedWindow(self.root, orient=tk.HORIZONTAL)
        self.paned_window.pack(fill=tk.BOTH, expand=True)
        
        # 左侧笔记树框架
        self.tree_frame = tk.Frame(self.paned_window, width=200)
        self.paned_window.add(self.tree_frame)
        
        # 创建笔记树
        self.create_notes_tree()
        
        # 右侧主框架
        self.main_frame = tk.Frame(self.paned_window)
        self.paned_window.add(self.main_frame)
        
        # 查找替换工具栏（默认隐藏）
        self.find_toolbar = tk.Frame(self.main_frame, relief=tk.SUNKEN, bd=1)
        
        tk.Label(self.find_toolbar, text="查找:").pack(side=tk.LEFT, padx=2)
        self.find_entry = tk.Entry(self.find_toolbar, width=20)
        self.find_entry.pack(side=tk.LEFT, padx=2)
        
        self.case_var = tk.BooleanVar()
        self.case_check = tk.Checkbutton(self.find_toolbar, text="区分大小写", variable=self.case_var)
        self.case_check.pack(side=tk.LEFT, padx=2)
        
        tk.Button(self.find_toolbar, text="查找下一个", command=self.find_next).pack(side=tk.LEFT, padx=2)
        tk.Button(self.find_toolbar, text="查找上一个", command=self.find_previous).pack(side=tk.LEFT, padx=2)
        tk.Button(self.find_toolbar, text="替换", command=self.show_replace_dialog).pack(side=tk.LEFT, padx=2)
        tk.Button(self.find_toolbar, text="关闭", command=self.hide_find_toolbar).pack(side=tk.LEFT, padx=2)

        # 主文本框区域（带滚动条）
        self.text_area = scrolledtext.ScrolledText(self.main_frame, wrap=tk.WORD, undo=True, maxundo=100)
        self.text_area.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 状态栏
        self.status_bar = tk.Label(self.main_frame, text="就绪", bd=1, relief=tk.SUNKEN, anchor=tk.W)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 创建菜单栏
        self.create_menus()

    def create_notes_tree(self):
        """创建笔记树状结构"""
        # 工具栏
        tree_toolbar = tk.Frame(self.tree_frame)
        tree_toolbar.pack(fill=tk.X)
        
        tk.Button(tree_toolbar, text="新建文件夹", command=self.create_new_folder).pack(side=tk.LEFT, padx=2, pady=2)
        tk.Button(tree_toolbar, text="刷新", command=self.load_notes_tree).pack(side=tk.LEFT, padx=2, pady=2)
        
        # 排序选项
        sort_frame = tk.Frame(self.tree_frame)
        sort_frame.pack(fill=tk.X, padx=2, pady=2)
        
        tk.Label(sort_frame, text="排序:").pack(side=tk.LEFT)
        self.sort_var = tk.StringVar(value="modified")
        sort_combo = ttk.Combobox(sort_frame, textvariable=self.sort_var, 
                                 values=["created", "modified", "title"], state="readonly", width=10)
        sort_combo.pack(side=tk.LEFT, padx=2)
        sort_combo.bind("<<ComboboxSelected>>", self.on_sort_changed)
        
        # 树状视图
        tree_container = tk.Frame(self.tree_frame)
        tree_container.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
        
        # 添加滚动条
        tree_scroll = tk.Scrollbar(tree_container)
        tree_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.notes_tree = ttk.Treeview(tree_container, yscrollcommand=tree_scroll.set)
        self.notes_tree.pack(fill=tk.BOTH, expand=True)
        
        tree_scroll.config(command=self.notes_tree.yview)
        
        # 配置树列
        self.notes_tree["columns"] = ("type", "modified")
        self.notes_tree.column("#0", width=150, minwidth=100)
        self.notes_tree.column("type", width=60, minwidth=50)
        self.notes_tree.column("modified", width=120, minwidth=100)
        
        # 设置表头
        self.notes_tree.heading("#0", text="名称", anchor=tk.W)
        self.notes_tree.heading("type", text="类型", anchor=tk.W)
        self.notes_tree.heading("modified", text="修改时间", anchor=tk.W)
        
        # 绑定事件
        self.notes_tree.bind("<Button-1>", self.on_tree_click)
        self.notes_tree.bind("<Double-1>", self.on_tree_double_click)
        self.notes_tree.bind("<Button-3>", self.show_tree_context_menu)

    def create_menus(self):
        """创建菜单栏"""
        self.menu_bar = tk.Menu(self.root)
        self.root.config(menu=self.menu_bar)

        # 文件菜单
        self.file_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="文件", menu=self.file_menu)
        self.file_menu.add_command(label="新建笔记", command=self.new_note, accelerator="Ctrl+N")
        self.file_menu.add_command(label="打开...", command=self.open_file, accelerator="Ctrl+O")
        self.file_menu.add_separator()
        self.file_menu.add_command(label="保存", command=self.save_file, accelerator="Ctrl+S")
        self.file_menu.add_command(label="另存为...", command=self.save_as_file)
        self.file_menu.add_separator()
        self.file_menu.add_command(label="备份设置", command=self.show_backup_settings)
        self.file_menu.add_command(label="立即备份", command=self.create_backup)
        self.file_menu.add_separator()
        self.file_menu.add_command(label="退出", command=self.exit_app)

        # 编辑菜单
        self.edit_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="编辑", menu=self.edit_menu)
        self.edit_menu.add_command(label="撤销", command=self.undo, accelerator="Ctrl+Z")
        self.edit_menu.add_command(label="重做", command=self.redo, accelerator="Ctrl+Y")
        self.edit_menu.add_separator()
        self.edit_menu.add_command(label="剪切", command=self.cut, accelerator="Ctrl+X")
        self.edit_menu.add_command(label="复制", command=self.copy, accelerator="Ctrl+C")
        self.edit_menu.add_command(label="粘贴", command=self.paste, accelerator="Ctrl+V")
        self.edit_menu.add_command(label="粘贴历史", command=self.show_clipboard_history)
        self.edit_menu.add_separator()
        self.edit_menu.add_command(label="全选", command=self.select_all, accelerator="Ctrl+A")
        self.edit_menu.add_command(label="查找", command=self.show_find_toolbar, accelerator="Ctrl+F")
        self.edit_menu.add_command(label="替换", command=self.show_replace_dialog, accelerator="Ctrl+H")

        # 笔记菜单
        self.notes_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="笔记", menu=self.notes_menu)
        self.notes_menu.add_command(label="新建文件夹", command=self.create_new_folder)
        self.notes_menu.add_command(label="重命名", command=self.rename_item)
        self.notes_menu.add_command(label="移动到", command=self.move_item)
        self.notes_menu.add_command(label="删除", command=self.delete_item)
        self.notes_menu.add_separator()
        self.notes_menu.add_command(label="批量操作", command=self.show_batch_operations)
        self.notes_menu.add_command(label="回收站", command=self.show_recycle_bin)

        # 格式菜单
        self.format_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="格式", menu=self.format_menu)
        
        # 字体子菜单
        self.font_menu = tk.Menu(self.format_menu, tearoff=0)
        self.format_menu.add_cascade(label="字体", menu=self.font_menu)
        
        # 获取系统字体（简化版）
        fonts = ["Arial", "Times New Roman", "Courier New", "微软雅黑", "宋体", "黑体"]
        for font in fonts:
            self.font_menu.add_command(label=font, command=lambda f=font: self.change_font(f))
        
        # 字号子菜单
        self.size_menu = tk.Menu(self.format_menu, tearoff=0)
        self.format_menu.add_cascade(label="字号", menu=self.size_menu)
        
        sizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32]
        for size in sizes:
            self.size_menu.add_command(label=str(size), command=lambda s=size: self.change_font_size(s))
        
        self.format_menu.add_separator()
        self.format_menu.add_command(label="粗体", command=self.toggle_bold, accelerator="Ctrl+B")
        self.format_menu.add_command(label="斜体", command=self.toggle_italic, accelerator="Ctrl+I")
        self.format_menu.add_command(label="下划线", command=self.toggle_underline, accelerator="Ctrl+U")
        self.format_menu.add_command(label="删除线", command=self.toggle_strikethrough)
        self.format_menu.add_separator()
        self.format_menu.add_command(label="文字颜色", command=self.change_text_color)
        self.format_menu.add_command(label="背景颜色", command=self.change_bg_color)

        # 安全菜单
        self.security_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="安全", menu=self.security_menu)
        self.security_menu.add_command(label="加密笔记", command=self.encrypt_note)
        self.security_menu.add_command(label="解密笔记", command=self.decrypt_note)
        self.security_menu.add_command(label="设置加密密钥", command=self.set_encryption_key)

    def bind_events(self):
        """绑定键盘快捷键和事件"""
        # 文件操作快捷键
        self.root.bind('<Control-n>', lambda event: self.new_note())
        self.root.bind('<Control-o>', lambda event: self.open_file())
        self.root.bind('<Control-s>', lambda event: self.save_file())
        
        # 编辑操作快捷键
        self.root.bind('<Control-z>', lambda event: self.undo())
        self.root.bind('<Control-y>', lambda event: self.redo())
        self.root.bind('<Control-x>', lambda event: self.cut())
        self.root.bind('<Control-c>', lambda event: self.copy())
        self.root.bind('<Control-v>', lambda event: self.paste())
        self.root.bind('<Control-a>', lambda event: self.select_all())
        self.root.bind('<Control-f>', lambda event: self.show_find_toolbar())
        self.root.bind('<Control-h>', lambda event: self.show_replace_dialog())
        
        # 格式操作快捷键
        self.root.bind('<Control-b>', lambda event: self.toggle_bold())
        self.root.bind('<Control-i>', lambda event: self.toggle_italic())
        self.root.bind('<Control-u>', lambda event: self.toggle_underline())
        
        # 监听文本修改
        self.text_area.bind('<<Modified>>', self.on_text_modified)
        # 绑定窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.exit_app)
        
        # 绑定Alt键用于列选模式
        self.text_area.bind('<Alt-Button-1>', self.start_column_select)
        self.text_area.bind('<Alt-B1-Motion>', self.do_column_select)
        self.text_area.bind('<ButtonRelease-1>', self.end_column_select)

    # ========== 笔记组织管理功能 ==========

    def init_folder_structure(self):
        """初始化文件夹结构"""
        notes_dir = os.path.join(os.path.expanduser("~"), "NotepadNotes")
        if not os.path.exists(notes_dir):
            os.makedirs(notes_dir)
        
        # 创建配置文件
        config_file = os.path.join(notes_dir, ".notepad_config.json")
        if not os.path.exists(config_file):
            config = {
                "folders": {
                    "工作": {
                        "项目A": {
                            "需求文档": {}
                        }
                    },
                    "个人": {},
                    "学习": {}
                },
                "settings": {
                    "backup_enabled": True,
                    "backup_interval": "daily",
                    "encryption_enabled": False
                }
            }
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
        
        self.load_folder_structure()

    def load_folder_structure(self):
        """加载文件夹结构"""
        notes_dir = os.path.join(os.path.expanduser("~"), "NotepadNotes")
        config_file = os.path.join(notes_dir, ".notepad_config.json")
        
        if os.path.exists(config_file):
            with open(config_file, 'r', encoding='utf-8') as f:
                config = json.load(f)
                self.folder_structure = config.get("folders", {})
        
        # 确保文件夹结构在磁盘上存在
        self.create_folders_from_structure(self.folder_structure, notes_dir)

    def create_folders_from_structure(self, structure, parent_path):
        """根据结构创建文件夹"""
        for name, children in structure.items():
            folder_path = os.path.join(parent_path, name)
            if not os.path.exists(folder_path):
                os.makedirs(folder_path)
            
            if children:
                self.create_folders_from_structure(children, folder_path)

    def load_notes_tree(self):
        """加载笔记树"""
        self.notes_tree.delete(*self.notes_tree.get_children())
        notes_dir = os.path.join(os.path.expanduser("~"), "NotepadNotes")
        self.add_tree_node("", notes_dir, "")

    def add_tree_node(self, parent, path, display_path):
        """添加树节点"""
        if not os.path.exists(path):
            return
        
        items = os.listdir(path)
        # 排序
        if self.sort_var.get() == "title":
            items.sort()
        elif self.sort_var.get() == "modified":
            items.sort(key=lambda x: os.path.getmtime(os.path.join(path, x)), reverse=True)
        else:  # created
            items.sort(key=lambda x: os.path.getctime(os.path.join(path, x)), reverse=True)
        
        for item in items:
            if item.startswith('.'):  # 跳过隐藏文件和配置
                continue
                
            item_path = os.path.join(path, item)
            item_display_path = os.path.join(display_path, item) if display_path else item
            
            if os.path.isdir(item_path):
                node_id = self.notes_tree.insert(parent, "end", text=item, values=("文件夹", ""))
                self.add_tree_node(node_id, item_path, item_display_path)
            elif item.endswith(('.txt', '.md')):
                mod_time = datetime.fromtimestamp(os.path.getmtime(item_path)).strftime("%Y-%m-%d %H:%M")
                self.notes_tree.insert(parent, "end", text=item, values=("笔记", mod_time), tags=(item_path,))

    def on_tree_click(self, event):
        """树节点点击事件"""
        item = self.notes_tree.identify('item', event.x, event.y)
        if item:
            values = self.notes_tree.item(item, "values")
            tags = self.notes_tree.item(item, "tags")
            if tags and values[0] == "笔记":  # 是笔记文件
                self.current_folder_path = os.path.dirname(tags[0])
            else:  # 是文件夹
                self.current_folder_path = self.get_full_path(item)

    def on_tree_double_click(self, event):
        """树节点双击事件"""
        item = self.notes_tree.identify('item', event.x, event.y)
        if item:
            values = self.notes_tree.item(item, "values")
            tags = self.notes_tree.item(item, "tags")
            
            if tags and values[0] == "笔记":  # 是笔记文件
                self.open_note_file(tags[0])

    def get_full_path(self, item):
        """获取节点的完整路径"""
        notes_dir = os.path.join(os.path.expanduser("~"), "NotepadNotes")
        parent = self.notes_tree.parent(item)
        path_parts = [self.notes_tree.item(item, "text")]
        
        while parent:
            path_parts.insert(0, self.notes_tree.item(parent, "text"))
            parent = self.notes_tree.parent(parent)
        
        return os.path.join(notes_dir, *path_parts)

    def show_tree_context_menu(self, event):
        """显示树上下文菜单"""
        item = self.notes_tree.identify('item', event.x, event.y)
        if item:
            menu = tk.Menu(self.root, tearoff=0)
            values = self.notes_tree.item(item, "values")
            
            if values[0] == "文件夹":
                menu.add_command(label="新建笔记", command=lambda: self.new_note_in_folder(item))
                menu.add_command(label="新建子文件夹", command=lambda: self.create_subfolder(item))
                menu.add_separator()
            
            menu.add_command(label="重命名", command=lambda: self.rename_item(item))
            menu.add_command(label="移动到", command=lambda: self.move_item(item))
            menu.add_command(label="删除", command=lambda: self.delete_item(item))
            
            menu.post(event.x_root, event.y_root)

    def on_sort_changed(self, event):
        """排序方式改变事件"""
        self.load_notes_tree()

    def create_new_folder(self):
        """创建新文件夹"""
        folder_name = simpledialog.askstring("新建文件夹", "请输入文件夹名称:")
        if folder_name:
            # 在当前选中的文件夹中创建新文件夹
            parent_path = self.current_folder_path or os.path.join(os.path.expanduser("~"), "NotepadNotes")
            new_folder_path = os.path.join(parent_path, folder_name)
            
            if not os.path.exists(new_folder_path):
                os.makedirs(new_folder_path)
                self.load_notes_tree()
            else:
                messagebox.showerror("错误", "文件夹已存在")

    def create_subfolder(self, parent_item):
        """创建子文件夹"""
        parent_path = self.get_full_path(parent_item)
        folder_name = simpledialog.askstring("新建子文件夹", "请输入子文件夹名称:")
        if folder_name:
            new_folder_path = os.path.join(parent_path, folder_name)
            
            if not os.path.exists(new_folder_path):
                os.makedirs(new_folder_path)
                self.load_notes_tree()
            else:
                messagebox.showerror("错误", "文件夹已存在")

    def new_note(self):
        """新建笔记"""
        if not self.check_save():
            return
        
        # 如果当前选中了文件夹，在该文件夹中创建笔记
        parent_path = self.current_folder_path or os.path.join(os.path.expanduser("~"), "NotepadNotes")
        
        note_name = simpledialog.askstring("新建笔记", "请输入笔记名称:")
        if note_name:
            if not note_name.endswith(('.txt', '.md')):
                note_name += '.txt'
            
            note_path = os.path.join(parent_path, note_name)
            
            if os.path.exists(note_path):
                messagebox.showerror("错误", "笔记已存在")
                return
            
            self.text_area.delete(1.0, tk.END)
            self.current_file = note_path
            self.dirty = True
            self.update_title()
            self.load_notes_tree()

    def new_note_in_folder(self, folder_item):
        """在指定文件夹中新建笔记"""
        folder_path = self.get_full_path(folder_item)
        self.current_folder_path = folder_path
        self.new_note()

    def rename_item(self, item):
        """重命名项目"""
        old_name = self.notes_tree.item(item, "text")
        new_name = simpledialog.askstring("重命名", "请输入新名称:", initialvalue=old_name)
        
        if new_name and new_name != old_name:
            old_path = self.get_full_path(item)
            
            if os.path.isfile(old_path) and not new_name.endswith(('.txt', '.md')):
                new_name += '.txt'
            
            new_path = os.path.join(os.path.dirname(old_path), new_name)
            
            if os.path.exists(new_path):
                messagebox.showerror("错误", "名称已存在")
                return
            
            os.rename(old_path, new_path)
            self.load_notes_tree()
            
            # 如果重命名的是当前打开的文件，更新当前文件引用
            if self.current_file == old_path:
                self.current_file = new_path
                self.update_title()

    def move_item(self, item):
        """移动项目"""
        # 弹出文件夹选择对话框
        target_folder = filedialog.askdirectory(
            initialdir=os.path.join(os.path.expanduser("~"), "NotepadNotes"),
            title="选择目标文件夹"
        )
        
        if target_folder:
            item_path = self.get_full_path(item)
            item_name = os.path.basename(item_path)
            target_path = os.path.join(target_folder, item_name)
            
            if os.path.exists(target_path):
                messagebox.showerror("错误", "目标位置已存在同名项目")
                return
            
            shutil.move(item_path, target_path)
            self.load_notes_tree()
            
            # 如果移动的是当前打开的文件，更新当前文件引用
            if self.current_file == item_path:
                self.current_file = target_path
                self.update_title()

    def delete_item(self, item):
        """删除项目"""
        if messagebox.askyesno("确认删除", "确定要删除该项目吗？\n删除后将移至回收站，30天后自动永久删除。"):
            item_path = self.get_full_path(item)
            recycle_bin = os.path.join(os.path.expanduser("~"), "NotepadRecycleBin")
            
            if not os.path.exists(recycle_bin):
                os.makedirs(recycle_bin)
            
            # 生成唯一文件名，避免冲突
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            item_name = os.path.basename(item_path)
            target_path = os.path.join(recycle_bin, f"{timestamp}_{item_name}")
            
            shutil.move(item_path, target_path)
            self.load_notes_tree()
            
            # 如果删除的是当前打开的文件，清空编辑器
            if self.current_file == item_path:
                self.text_area.delete(1.0, tk.END)
                self.current_file = None
                self.dirty = False
                self.update_title()

    def show_batch_operations(self):
        """显示批量操作对话框"""
        batch_window = tk.Toplevel(self.root)
        batch_window.title("批量操作")
        batch_window.geometry("400x300")
        
        # 这里可以实现批量选择、移动、删除、添加标签等功能
        tk.Label(batch_window, text="批量操作功能", font=("Arial", 14)).pack(pady=20)
        tk.Label(batch_window, text="选择要执行的操作:").pack(pady=10)
        
        operation_var = tk.StringVar(value="move")
        tk.Radiobutton(batch_window, text="移动", variable=operation_var, value="move").pack(anchor=tk.W, padx=20)
        tk.Radiobutton(batch_window, text="删除", variable=operation_var, value="delete").pack(anchor=tk.W, padx=20)
        tk.Radiobutton(batch_window, text="添加标签", variable=operation_var, value="add_tag").pack(anchor=tk.W, padx=20)
        tk.Radiobutton(batch_window, text="移除标签", variable=operation_var, value="remove_tag").pack(anchor=tk.W, padx=20)
        
        tk.Button(batch_window, text="执行", command=lambda: self.execute_batch_operation(operation_var.get())).pack(pady=20)

    def execute_batch_operation(self, operation):
        """执行批量操作"""
        # 这里可以实现具体的批量操作逻辑
        messagebox.showinfo("批量操作", f"执行 {operation} 操作")

    def show_recycle_bin(self):
        """显示回收站"""
        recycle_bin = os.path.join(os.path.expanduser("~"), "NotepadRecycleBin")
        
        if not os.path.exists(recycle_bin):
            messagebox.showinfo("回收站", "回收站为空")
            return
        
        bin_window = tk.Toplevel(self.root)
        bin_window.title("回收站")
        bin_window.geometry("600x400")
        
        # 创建列表显示删除的项目
        frame = tk.Frame(bin_window)
        frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        scrollbar = tk.Scrollbar(frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        listbox = tk.Listbox(frame, yscrollcommand=scrollbar.set)
        listbox.pack(fill=tk.BOTH, expand=True)
        
        scrollbar.config(command=listbox.yview)
        
        # 添加删除的项目到列表
        for item in os.listdir(recycle_bin):
            item_path = os.path.join(recycle_bin, item)
            if os.path.isfile(item_path):
                # 解析时间戳和原始文件名
                parts = item.split('_', 2)
                if len(parts) >= 3:
                    timestamp = f"{parts[0]}_{parts[1]}"
                    original_name = parts[2]
                    mod_time = datetime.fromtimestamp(os.path.getmtime(item_path))
                    
                    listbox.insert(tk.END, f"{original_name} - 删除时间: {timestamp}")
        
        # 添加恢复和永久删除按钮
        button_frame = tk.Frame(bin_window)
        button_frame.pack(fill=tk.X, padx=5, pady=5)
        
        tk.Button(button_frame, text="恢复", command=lambda: self.restore_item(listbox, recycle_bin)).pack(side=tk.LEFT)
        tk.Button(button_frame, text="永久删除", command=lambda: self.permanent_delete(listbox, recycle_bin)).pack(side=tk.LEFT)
        tk.Button(button_frame, text="清空回收站", command=lambda: self.empty_recycle_bin(recycle_bin, listbox)).pack(side=tk.RIGHT)

    def restore_item(self, listbox, recycle_bin):
        """恢复项目"""
        selection = listbox.curselection()
        if not selection:
            return
        
        selected_index = selection[0]
        selected_text = listbox.get(selected_index)
        original_name = selected_text.split(' - ')[0]
        
        # 查找对应的文件
        for item in os.listdir(recycle_bin):
            if item.endswith(original_name):
                item_path = os.path.join(recycle_bin, item)
                restore_path = os.path.join(os.path.expanduser("~"), "NotepadNotes", original_name)
                
                # 检查是否已存在同名文件
                if os.path.exists(restore_path):
                    messagebox.showerror("错误", "目标位置已存在同名文件")
                    return
                
                shutil.move(item_path, restore_path)
                listbox.delete(selected_index)
                self.load_notes_tree()
                break

    def permanent_delete(self, listbox, recycle_bin):
        """永久删除项目"""
        selection = listbox.curselection()
        if not selection:
            return
        
        selected_index = selection[0]
        selected_text = listbox.get(selected_index)
        original_name = selected_text.split(' - ')[0]
        
        # 查找对应的文件
        for item in os.listdir(recycle_bin):
            if item.endswith(original_name):
                item_path = os.path.join(recycle_bin, item)
                os.remove(item_path)
                listbox.delete(selected_index)
                break

    def empty_recycle_bin(self, recycle_bin, listbox):
        """清空回收站"""
        if messagebox.askyesno("确认清空", "确定要清空回收站吗？此操作不可恢复。"):
            for item in os.listdir(recycle_bin):
                item_path = os.path.join(recycle_bin, item)
                if os.path.isfile(item_path):
                    os.remove(item_path)
            
            listbox.delete(0, tk.END)

    # ========== 存储优化功能 ==========

    def show_backup_settings(self):
        """显示备份设置"""
        settings_window = tk.Toplevel(self.root)
        settings_window.title("备份设置")
        settings_window.geometry("400x300")
        
        # 加载当前设置
        config_file = os.path.join(os.path.expanduser("~"), "NotepadNotes", ".notepad_config.json")
        backup_enabled = True
        backup_interval = "daily"
        
        if os.path.exists(config_file):
            with open(config_file, 'r', encoding='utf-8') as f:
                config = json.load(f)
                backup_enabled = config.get("settings", {}).get("backup_enabled", True)
                backup_interval = config.get("settings", {}).get("backup_interval", "daily")
        
        # 备份启用选项
        backup_var = tk.BooleanVar(value=backup_enabled)
        tk.Checkbutton(settings_window, text="启用自动备份", variable=backup_var).pack(anchor=tk.W, padx=20, pady=10)
        
        tk.Label(settings_window, text="备份频率:").pack(anchor=tk.W, padx=20, pady=5)
        interval_var = tk.StringVar(value=backup_interval)
        tk.Radiobutton(settings_window, text="每天", variable=interval_var, value="daily").pack(anchor=tk.W, padx=40)
        tk.Radiobutton(settings_window, text="每周", variable=interval_var, value="weekly").pack(anchor=tk.W, padx=40)
        
        # 备份路径
        tk.Label(settings_window, text="备份路径:").pack(anchor=tk.W, padx=20, pady=5)
        path_frame = tk.Frame(settings_window)
        path_frame.pack(fill=tk.X, padx=20, pady=5)
        
        path_var = tk.StringVar(value=self.backup_dir)
        path_entry = tk.Entry(path_frame, textvariable=path_var)
        path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        tk.Button(path_frame, text="浏览", command=lambda: self.choose_backup_path(path_var)).pack(side=tk.RIGHT)
        
        def save_settings():
            # 保存设置
            config = {
                "folders": self.folder_structure,
                "settings": {
                    "backup_enabled": backup_var.get(),
                    "backup_interval": interval_var.get(),
                    "backup_path": path_var.get()
                }
            }
            
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
            
            self.backup_dir = path_var.get()
            settings_window.destroy()
            messagebox.showinfo("设置", "备份设置已保存")
        
        tk.Button(settings_window, text="保存", command=save_settings).pack(pady=20)

    def choose_backup_path(self, path_var):
        """选择备份路径"""
        path = filedialog.askdirectory(initialdir=path_var.get())
        if path:
            path_var.set(path)

    def create_backup(self):
        """创建备份"""
        notes_dir = os.path.join(os.path.expanduser("~"), "NotepadNotes")
        if not os.path.exists(self.backup_dir):
            os.makedirs(self.backup_dir)
        
        # 创建带时间戳的备份文件夹
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_path = os.path.join(self.backup_dir, f"backup_{timestamp}")
        
        try:
            # 复制整个笔记目录
            shutil.copytree(notes_dir, backup_path)
            messagebox.showinfo("备份", f"备份已创建: {backup_path}")
        except Exception as e:
            messagebox.showerror("备份错误", f"创建备份时出错: {str(e)}")

    # ========== 安全与隐私功能 ==========

    def set_encryption_key(self):
        """设置加密密钥"""
        key = simpledialog.askstring("加密密钥", "请输入加密密钥（至少16个字符）:", show='*')
        if key and len(key) >= 16:
            self.encryption_key = key.encode('utf-8')
            messagebox.showinfo("加密", "加密密钥已设置")
        elif key:
            messagebox.showerror("错误", "密钥长度必须至少16个字符")

    def encrypt_note(self):
        """加密笔记"""
        if not self.encryption_key:
            messagebox.showerror("错误", "请先设置加密密钥")
            return
        
        if not self.current_file:
            messagebox.showerror("错误", "请先保存笔记")
            return
        
        try:
            # 读取笔记内容
            with open(self.current_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 加密内容
            cipher = AES.new(self.encryption_key, AES.MODE_CBC)
            ct_bytes = cipher.encrypt(pad(content.encode('utf-8'), AES.block_size))
            iv = base64.b64encode(cipher.iv).decode('utf-8')
            ct = base64.b64encode(ct_bytes).decode('utf-8')
            encrypted_content = iv + ct
            
            # 写入加密内容
            with open(self.current_file, 'w', encoding='utf-8') as f:
                f.write(encrypted_content)
            
            # 更新编辑器内容
            self.text_area.delete(1.0, tk.END)
            self.text_area.insert(1.0, "[加密内容 - 需要解密才能查看]")
            
            messagebox.showinfo("加密", "笔记已加密")
        except Exception as e:
            messagebox.showerror("加密错误", f"加密时出错: {str(e)}")

    def decrypt_note(self):
        """解密笔记"""
        if not self.encryption_key:
            messagebox.showerror("错误", "请先设置加密密钥")
            return
        
        if not self.current_file:
            messagebox.showerror("错误", "没有打开任何笔记")
            return
        
        try:
            # 读取加密内容
            with open(self.current_file, 'r', encoding='utf-8') as f:
                encrypted_content = f.read()
            
            # 检查内容是否确实是加密的
            if not encrypted_content.startswith('eyJ') and len(encrypted_content) > 24:  # 简单检查
                messagebox.showerror("错误", "此笔记未加密或格式不正确")
                return
            
            # 提取IV和密文
            iv = base64.b64decode(encrypted_content[:24])
            ct = base64.b64decode(encrypted_content[24:])
            
            # 解密
            cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv)
            pt = unpad(cipher.decrypt(ct), AES.block_size)
            content = pt.decode('utf-8')
            
            # 更新编辑器内容
            self.text_area.delete(1.0, tk.END)
            self.text_area.insert(1.0, content)
            
            # 保存解密后的内容
            with open(self.current_file, 'w', encoding='utf-8') as f:
                f.write(content)
            
            messagebox.showinfo("解密", "笔记已解密")
        except Exception as e:
            messagebox.showerror("解密错误", f"解密时出错: {str(e)}")

    # ========== 原有的基础功能 ==========

    def open_note_file(self, file_path):
        """打开笔记文件"""
        if not self.check_save():
            return
        
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()
            self.text_area.delete(1.0, tk.END)
            self.text_area.insert(1.0, content)
            self.current_file = file_path
            self.dirty = False
            self.update_title()
        except Exception as e:
            messagebox.showerror("错误", f"无法打开文件：\n{str(e)}")

    def on_text_modified(self, event=None):
        if self.text_area.edit_modified():
            self.dirty = True
            self.update_title()
        self.text_area.edit_modified(False)

    def update_title(self):
        base_title = "高级记事本"
        if self.current_file:
            title = f"{Path(self.current_file).name} - {base_title}"
        else:
            title = "无标题 - " + base_title
        if self.dirty:
            title = "*" + title
        self.root.title(title)

    def new_file(self):
        if not self.check_save():
            return
        self.text_area.delete(1.0, tk.END)
        self.current_file = None
        self.dirty = False
        self.update_title()

    def open_file(self):
        if not self.check_save():
            return
        file_path = filedialog.askopenfilename(
            filetypes=[("文本文件", "*.txt"), ("Markdown文件", "*.md"), ("所有文件", "*.*")]
        )
        if file_path:
            self.open_note_file(file_path)

    def save_file(self):
        if self.current_file:
            return self._save_to_file(self.current_file)
        else:
            return self.save_as_file()

    def save_as_file(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("Markdown文件", "*.md"), ("所有文件", "*.*")]
        )
        if file_path:
            if self._save_to_file(file_path):
                self.current_file = file_path
                self.update_title()
                self.load_notes_tree()
                return True
        return False

    def _save_to_file(self, file_path):
        try:
            content = self.text_area.get(1.0, tk.END)
            with open(file_path, 'w', encoding='utf-8') as file:
                file.write(content)
            self.dirty = False
            self.update_title()
            return True
        except Exception as e:
            messagebox.showerror("错误", f"保存文件失败：\n{str(e)}")
            return False

    def check_save(self):
        if self.dirty:
            response = messagebox.askyesnocancel("保存更改", "当前内容已修改，是否保存更改？")
            if response is None:
                return False
            elif response:
                return self.save_file()
        return True

    def exit_app(self):
        if self.check_save():
            # 清理回收站中超过30天的文件
            self.cleanup_recycle_bin()
            self.root.destroy()

    def cleanup_recycle_bin(self):
        """清理回收站中超过30天的文件"""
        recycle_bin = os.path.join(os.path.expanduser("~"), "NotepadRecycleBin")
        if not os.path.exists(recycle_bin):
            return
        
        thirty_days_ago = datetime.now() - timedelta(days=30)
        
        for item in os.listdir(recycle_bin):
            item_path = os.path.join(recycle_bin, item)
            if os.path.isfile(item_path):
                mod_time = datetime.fromtimestamp(os.path.getmtime(item_path))
                if mod_time < thirty_days_ago:
                    os.remove(item_path)

    # ========== 文本编辑增强功能 ==========

    def undo(self):
        """撤销操作"""
        try:
            self.text_area.edit_undo()
        except tk.TclError:
            pass  # 没有可撤销的操作

    def redo(self):
        """重做操作"""
        try:
            self.text_area.edit_redo()
        except tk.TclError:
            pass  # 没有可重做的操作

    def cut(self):
        """剪切文本"""
        if self.text_area.tag_ranges(tk.SEL):
            self.copy()  # 先复制到剪贴板
            self.text_area.delete(tk.SEL_FIRST, tk.SEL_LAST)
            self.add_to_clipboard_history(self.root.clipboard_get())

    def copy(self):
        """复制文本"""
        if self.text_area.tag_ranges(tk.SEL):
            self.text_area.event_generate("<<Copy>>")
            self.add_to_clipboard_history(self.root.clipboard_get())

    def paste(self):
        """粘贴文本"""
        self.text_area.event_generate("<<Paste>>")
        self.dirty = True
        self.update_title()

    def add_to_clipboard_history(self, text):
        """添加文本到剪贴板历史"""
        if text and text not in self.clipboard_history:
            self.clipboard_history.insert(0, text)
            # 限制历史记录数量
            if len(self.clipboard_history) > self.max_clipboard_history:
                self.clipboard_history = self.clipboard_history[:self.max_clipboard_history]

    def show_clipboard_history(self):
        """显示剪贴板历史"""
        if not self.clipboard_history:
            messagebox.showinfo("剪贴板历史", "剪贴板历史为空")
            return
        
        history_window = tk.Toplevel(self.root)
        history_window.title("剪贴板历史")
        history_window.geometry("400x300")
        
        listbox = tk.Listbox(history_window)
        listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        for i, item in enumerate(self.clipboard_history):
            # 显示前50个字符
            display_text = item[:50] + "..." if len(item) > 50 else item
            listbox.insert(tk.END, f"{i+1}. {display_text}")
        
        def paste_selected():
            selection = listbox.curselection()
            if selection:
                selected_text = self.clipboard_history[selection[0]]
                self.text_area.insert(tk.INSERT, selected_text)
                history_window.destroy()
        
        button_frame = tk.Frame(history_window)
        button_frame.pack(fill=tk.X, padx=5, pady=5)
        
        tk.Button(button_frame, text="粘贴选中", command=paste_selected).pack(side=tk.LEFT)
        tk.Button(button_frame, text="关闭", command=history_window.destroy).pack(side=tk.RIGHT)

    def select_all(self):
        """全选文本"""
        self.text_area.tag_add(tk.SEL, "1.0", tk.END)
        self.text_area.mark_set(tk.INSERT, "1.0")
        self.text_area.see(tk.INSERT)
        return "break"  # 阻止默认行为

    def start_column_select(self, event):
        """开始列选模式"""
        self.column_select_start = (event.x, event.y)
        self.text_area.mark_set("column_anchor", f"@{event.x},{event.y}")

    def do_column_select(self, event):
        """执行列选"""
        self.text_area.tag_remove(tk.SEL, "1.0", tk.END)
        start_x, start_y = self.column_select_start
        self.text_area.tag_add(tk.SEL, f"@{start_x},{start_y}", f"@{event.x},{event.y}")

    def end_column_select(self, event):
        """结束列选"""
        if hasattr(self, 'column_select_start'):
            delattr(self, 'column_select_start')

    def show_find_toolbar(self):
        """显示查找工具栏"""
        self.find_toolbar.pack(fill=tk.X, before=self.text_area)
        self.find_entry.focus_set()

    def hide_find_toolbar(self):
        """隐藏查找工具栏"""
        self.find_toolbar.pack_forget()

    def find_next(self):
        """查找下一个"""
        self._find_text(forward=True)

    def find_previous(self):
        """查找上一个"""
        self._find_text(forward=False)

    def _find_text(self, forward=True):
        """执行查找操作"""
        search_term = self.find_entry.get()
        if not search_term:
            return
        
        self.find_data["last_search"] = search_term
        self.find_data["case_sensitive"] = self.case_var.get()
        
        start_pos = self.text_area.index(tk.INSERT)
        if forward:
            pos = self.text_area.search(search_term, start_pos, tk.END, 
                                      nocase=not self.case_var.get())
        else:
            # 反向查找需要从当前位置向前搜索
            content = self.text_area.get("1.0", start_pos)
            # 简单的反向查找实现
            if self.case_var.get():
                index = content.rfind(search_term)
            else:
                index = content.lower().rfind(search_term.lower())
            
            if index != -1:
                pos = f"1.0 + {index} chars"
            else:
                pos = ""
        
        if pos:
            self.text_area.tag_remove(tk.SEL, "1.0", tk.END)
            self.text_area.tag_add(tk.SEL, pos, f"{pos} + {len(search_term)} chars")
            self.text_area.mark_set(tk.INSERT, f"{pos} + {len(search_term)} chars")
            self.text_area.see(tk.INSERT)
        else:
            messagebox.showinfo("查找", "找不到匹配的文本")

    def show_replace_dialog(self):
        """显示替换对话框"""
        replace_window = tk.Toplevel(self.root)
        replace_window.title("替换")
        replace_window.geometry("300x150")
        
        tk.Label(replace_window, text="查找:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=2)
        find_entry = tk.Entry(replace_window, width=20)
        find_entry.grid(row=0, column=1, padx=5, pady=2)
        
        tk.Label(replace_window, text="替换为:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=2)
        replace_entry = tk.Entry(replace_window, width=20)
        replace_entry.grid(row=1, column=1, padx=5, pady=2)
        
        case_var = tk.BooleanVar()
        tk.Checkbutton(replace_window, text="区分大小写", variable=case_var).grid(row=2, column=0, columnspan=2, sticky=tk.W, padx=5)
        
        def do_replace():
            find_text = find_entry.get()
            replace_text = replace_entry.get()
            if find_text:
                content = self.text_area.get("1.0", tk.END)
                if case_var.get():
                    new_content = content.replace(find_text, replace_text)
                else:
                    # 不区分大小写替换
                    import re
                    new_content = re.sub(re.escape(find_text), replace_text, content, flags=re.IGNORECASE)
                
                self.text_area.delete("1.0", tk.END)
                self.text_area.insert("1.0", new_content)
                replace_window.destroy()
        
        button_frame = tk.Frame(replace_window)
        button_frame.grid(row=3, column=0, columnspan=2, pady=10)
        
        tk.Button(button_frame, text="替换全部", command=do_replace).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="取消", command=replace_window.destroy).pack(side=tk.LEFT, padx=5)

    # ========== 格式调整功能 ==========

    def change_font(self, font_name):
        """更改字体"""
        current_tags = self.text_area.tag_names(tk.SEL_FIRST) if self.text_area.tag_ranges(tk.SEL) else []
        if current_tags:
            for tag in current_tags:
                if tag.startswith("font_"):
                    self.text_area.tag_delete(tag)
            self.text_area.tag_configure(f"font_{font_name}", font=(font_name, self.get_current_size()))
            self.text_area.tag_add(f"font_{font_name}", tk.SEL_FIRST, tk.SEL_LAST)
        else:
            self.text_area.configure(font=(font_name, self.get_current_size()))

    def change_font_size(self, size):
        """更改字号"""
        current_font = self.text_area.cget("font")
        font_name = "Arial"  # 默认字体
        if current_font:
            font_name = current_font[0] if isinstance(current_font, tuple) else "Arial"
        
        self.text_area.configure(font=(font_name, size))

    def get_current_size(self):
        """获取当前字号"""
        current_font = self.text_area.cget("font")
        if isinstance(current_font, tuple) and len(current_font) > 1:
            return current_font[1]
        return 12  # 默认字号

    def toggle_bold(self):
        """切换粗体"""
        self._toggle_text_tag("bold", "bold", weight="bold")

    def toggle_italic(self):
        """切换斜体"""
        self._toggle_text_tag("italic", "italic", slant="italic")

    def toggle_underline(self):
        """切换下划线"""
        self._toggle_text_tag("underline", "underline", underline=1)

    def toggle_strikethrough(self):
        """切换删除线"""
        self._toggle_text_tag("strikethrough", "overstrike", overstrike=1)

    def _toggle_text_tag(self, tag_name, style, **kwargs):
        """通用的标签切换函数"""
        if self.text_area.tag_ranges(tk.SEL):
            if tag_name in self.text_area.tag_names(tk.SEL_FIRST):
                self.text_area.tag_remove(tag_name, tk.SEL_FIRST, tk.SEL_LAST)
            else:
                self.text_area.tag_configure(tag_name, **kwargs)
                self.text_area.tag_add(tag_name, tk.SEL_FIRST, tk.SEL_LAST)
        else:
            # 如果没有选中文本，改变默认样式
            current_config = self.text_area.cget(style)
            new_value = not current_config if isinstance(current_config, bool) else True
            self.text_area.configure(**{style: new_value})

    def change_text_color(self):
        """更改文字颜色"""
        color = colorchooser.askcolor(title="选择文字颜色")
        if color[1]:  # color[1] 是十六进制颜色代码
            if self.text_area.tag_ranges(tk.SEL):
                self.text_area.tag_configure("color", foreground=color[1])
                self.text_area.tag_add("color", tk.SEL_FIRST, tk.SEL_LAST)
            else:
                self.text_area.configure(foreground=color[1])

    def change_bg_color(self):
        """更改背景颜色"""
        color = colorchooser.askcolor(title="选择背景颜色")
        if color[1]:
            if self.text_area.tag_ranges(tk.SEL):
                self.text_area.tag_configure("bgcolor", background=color[1])
                self.text_area.tag_add("bgcolor", tk.SEL_FIRST, tk.SEL_LAST)
            else:
                self.text_area.configure(background=color[1])

def main():
    root = tk.Tk()
    root.geometry("1000x600")
    app = SimpleNotepad(root)
    root.mainloop()

if __name__ == "__main__":
    main()